#include <iostream>
using std::cout;
using std::endl;

class Data
{
public:
    Data(){}
    ~Data(){}

    int getData() const{ return _data; }
private:
    int _data = 10;
};

class MiddleLayer
{
public:
    MiddleLayer(Data * p)
    : _pdata(p)
    {}

    ~MiddleLayer(){
        if(_pdata){
            delete _pdata;
            _pdata = nullptr;
        }
    }

    Data * operator->(){
        return _pdata;
    }

    Data & operator*(){
        return *_pdata;
    }
private:
    Data * _pdata;
};

class ThirdLayer
{
public:
    ThirdLayer(MiddleLayer * pml)
    : _pml(pml)
    {}

    ~ThirdLayer(){
        if(_pml){
            delete _pml;
            _pml = nullptr;
        }
    }

    MiddleLayer & operator->(){
        return *_pml;
    }

    //一步一步解引用
    MiddleLayer & operator*(){
        return *_pml;
    }
private:
    MiddleLayer * _pml;
};


void test0(){
    //原生指针的用法
    Data * pd = new Data();
    cout << pd->getData() << endl;
    cout << (*pd).getData() << endl;

    MiddleLayer ml(pd);
    /* delete pd; */
}

void test1(){
    Data * p1 = new Data();
    cout << p1->getData() << endl;
    cout << (*p1).getData() << endl;
    delete p1;

    //更推荐这样使用MiddleLayer对象
    MiddleLayer ml(new Data());

    //编译器会自动加上一个->
    //第一个->和operator连在一起作为函数名
    //第二个->就是原生的箭头运算符用法
    /* cout << (ml.operator->())->getData() << endl; */
    cout << ml->getData() << endl;

    /* cout << (ml.operator*()).getData() << endl; */
    cout << (*ml).getData() << endl;

    //MiddleLayer对象已经和Data*类型的原生指针
    //拥有类似的功能
    //能够管理Data对象，还能访问Data对象的成员
    //MiddleLayer对象还能自动释放其管理的Data对象的空间
    //智能指针的雏形
    //利用对象的生命周期回收资源

    /* ThirdLayer tl(&ml);//error */
}

void test2(){
    MiddleLayer * pml = new MiddleLayer(new Data());
    ThirdLayer tl(pml);
    /* delete pml; */
}

void test3(){
    ThirdLayer tl(new MiddleLayer(new Data()));

    //第一个operator->函数是ThirdLayer的成员函数
    //第二个operator->函数是MiddleLayer的成员函数
    //最后一个->是编译器加上的，原生箭头运算符的用法
    /* cout << ((tl.operator->()).operator->())->getData() << endl; */

    //ThirdLayer对象的operator->函数只需要返回MiddleLayer对象
    //因为MiddleLayer类中已经重载了箭头运算符作为铺垫
    //所以MiddleLayer对象可以直接用->访问Data类的成员
    /* cout << (tl.operator->())->getData() << endl; */
    cout << tl->getData() << endl;

    //一步一步解引用
    /* cout << ((tl.operator*()).operator*()).getData() << endl; */
    cout << (*(*tl)).getData() << endl;


    /* cout << (*tl).getData() << endl; */
}

int main(void){
    test3();
    return 0;
}
